﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Drawing.Drawing2D;
//MicroDesigner
using Jc.MicroDesigner.Management;
using Jc.MicroDesigner.Objects;

namespace Jc.MicroDesigner.ToolWindows
{
    /// <summary>
    /// Форма редактирования свойств элемента - контейнера
    /// </summary>
    public partial class ContainerEditorForm : Form
    {
        ObjectManager _Manager = null;
        CompositeView _View = new CompositeView();
        double _ImgMultiplier = 1.0;

        Image _Template = null;

        /// <summary>
        /// Редактировать элемент
        /// </summary>
        /// <param name="element">Составной объект</param>
        public ContainerEditorForm(CompositeElement element)
        {
            InitializeComponent();
        }

        /// <summary>
        /// Показать диалог
        /// </summary>
        /// <param name="manager">Схема</param>
        public void ShowDialog(ObjectManager manager)
        {
            _Manager = manager;
            ShowDialog();
        }

        /// <summary>
        /// Обновить отображение с разметкой
        /// </summary>
        public void RefreshImg()
        {
            if (File.Exists(_View.ImgPath))
            {
                if (_Template == null)
                    _Template = Image.FromFile(_View.ImgPath);
                Image buffer = (Image)_Template.Clone();
                //рисуем сверху области пинов и точки контакта
                Graphics g = Graphics.FromImage(buffer);
                Pen p = new Pen(Color.Green);
                Brush px = new SolidBrush(Color.Red);
                p.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
                foreach (GateView gate in _View.Views)
                {
                    g.DrawRectangle(p, gate.Left, gate.Top, gate.Width, gate.Height);
                    g.FillRectangle(px, gate.BindX - 1, gate.BindY - 1, 4, 4);
                }
                //Применяем изображение
                ImgBox.Image = buffer;
                SetImage(ImgBox, _ImgMultiplier);
            }
        }

        #region Масштабирование изображения

        //новый размер изображения
        private Size GenerateImageDimensions(int currW, int currH, double multiplier)
        {
            //return the new image dimensions
            return new Size((int)(currW * multiplier), (int)(currH * multiplier));
        }

        //Resize the image
        private void SetImage(PictureBox pb, double mult)
        {
            try
            {
                //create a temp image
                Image img = pb.Image;
                //calculate the size of the image
                Size imgSize = GenerateImageDimensions(img.Width, img.Height, mult);
                //create a new Bitmap with the proper dimensions
                Bitmap finalImg = new Bitmap(img, imgSize.Width, imgSize.Height);
                //create a new Graphics object from the image
                Graphics gfx = Graphics.FromImage(img);
                //clean up the image (take care of any image loss from resizing)
                gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
                //empty the PictureBox
                pb.Image = null;
                //center the new image
                pb.SizeMode = PictureBoxSizeMode.CenterImage;
                //set the new image
                pb.Image = finalImg;
            }
            catch (System.Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }

        private void ClearImg()
        {
            _View.ImgPath = "";
            _Template = null;
            ImgBox.Image = null;
            _ImgMultiplier = 1.0;
        }

        #endregion

        /// <summary>
        /// Обновить имя i-ого пина
        /// </summary>
        /// <param name="i"></param>
        private void CalcName(int i)
        {
            PINListBox.Items[i] = (i + 1).ToString() + " :: " + PIN.TypeToString(_View.Views[i].PinType);
        }

        private void SaveElement(string filename)
        {
            //Собираем CompositeElement
            _View.Description = DescriptionBox.Text;
            _View.Name = NameTxtBox.Text;

            CompositeElement el = CompositeElement.Create(_Manager, _View);
            File.Create(filename).Close();
            FileInfo xmlfile = new FileInfo(filename);
            if (File.Exists(_View.ImgPath))
            {
                FileInfo imgfile = new FileInfo(_View.ImgPath);
                //Сохраняем изображение рядом с конфигом
                string new_img_path = xmlfile.Directory.FullName + Path.DirectorySeparatorChar + imgfile.Name;
                if (_View.ImgPath != new_img_path)
                    File.Copy(_View.ImgPath, new_img_path, true);
            }
            System.Xml.XmlDocument doc = SchemeSerializer.SaveCompositeElement(el);
            doc.Save(filename);
            MessageBox.Show("Элемент успешно установлен", "Уведомление", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        #region Events

        private void ClearImgBtn_Click(object sender, EventArgs e)
        {
            ClearImg();
        }

        private void AddPinBtn_Click(object sender, EventArgs e)
        {
            _View.Views.Add(new GateView(_Manager));
            int count = _View.Views.Count;
            PINListBox.Items.Add(count.ToString() + " :: " + PIN.TypeToString(_View.Views[count - 1].PinType));
        }

        private void RemovePinBtn_Click(object sender, EventArgs e)
        {
            int i = PINListBox.SelectedIndex;
            if (i >= 0)
            {
                _View.Views.RemoveAt(i);
                PINListBox.Items.RemoveAt(i);
                PinProps.SelectedObject = null;
                RefreshImg();
            }
        }

        private void PINListBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            int i = PINListBox.SelectedIndex;
            if (i >= 0)
                PinProps.SelectedObject = _View.Views[i];
        }

        private void LoadImgBtn_Click(object sender, EventArgs e)
        {
            if (ImgSelectDialog.ShowDialog() == DialogResult.OK)
            {
                ClearImg();
                _View.ImgPath = ImgSelectDialog.FileName;
                RefreshImg();
            }
        }

        private void PinProps_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            RefreshImg();
            int i = PINListBox.SelectedIndex;
            if (i >= 0)
            {
                CalcName(i);
            }
        }

        private void ZoomInBtn_Click(object sender, EventArgs e)
        {
            if (_ImgMultiplier < 5.0)
            {
                _ImgMultiplier += 0.2;
                RefreshImg();
            }
        }

        private void ZoomOutPtn_Click(object sender, EventArgs e)
        {
            if (_ImgMultiplier > 0.3)
            {
                _ImgMultiplier -= 0.2;
                RefreshImg();
            }
        }

        private void UpPinBtn_Click(object sender, EventArgs e)
        {
            int i = PINListBox.SelectedIndex;
            if (i >= 1)
            {
                GateView p = _View.Views[i];
                _View.Views[i] = _View.Views[i - 1];
                _View.Views[i - 1] = p;
                CalcName(i);
                CalcName(i - 1);
            }
        }

        private void DownPinBtn_Click(object sender, EventArgs e)
        {
            int i = PINListBox.SelectedIndex;
            if (i < PINListBox.Items.Count - 1)
            {
                GateView p = _View.Views[i];
                _View.Views[i] = _View.Views[i + 1];
                _View.Views[i + 1] = p;
                CalcName(i);
                CalcName(i + 1);
            }
        }

        private void сохранитьЭлементToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ElementSaveDialog.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    SaveElement(ElementSaveDialog.FileName);
                }
                catch (IOException ex)
                {
                    Jc.MicroDesigner.Exceptions.ExceptionDialog.ShowException(ex, "Ошибка сохранения",
                        "Во время сохранения произошла ошибка ввода-вывода.");
                }
                catch (Exception ex)
                {
                    Jc.MicroDesigner.Exceptions.ExceptionDialog.ShowException(ex, "Ошибка сохранения",
                        "Во время сохранения произошла ошибка.");
                }
            }
        }

        private void закрытьToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void установитьЭлементToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Сохранить элемент в папку Config/User
            try
            {
                string filename = _Manager.AppPath + "Config" +
                                                     Path.DirectorySeparatorChar + "User" +
                                                     Path.DirectorySeparatorChar + NameTxtBox.Text + ".xml";
                bool install = true;
                if (File.Exists(filename))
                    install = MessageBox.Show("Заменить существующий элемент ?", "Вопрос",
                        MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes;
                if (install)
                {
                    SaveElement(filename);
                }
            }
            catch (IOException ex)
            {
                Jc.MicroDesigner.Exceptions.ExceptionDialog.ShowException(ex, "Ошибка сохранения",
                    "Во время сохранения произошла ошибка ввода-вывода.");
            }
            catch (Exception ex)
            {
                Jc.MicroDesigner.Exceptions.ExceptionDialog.ShowException(ex, "Ошибка сохранения",
                    "Во время сохранения произошла ошибка.");
            }
        }
        #endregion
    }
}